import json
import random

from django.core.paginator import Paginator
from django.db import transaction
from decimal import Decimal
from django import http
from django.shortcuts import render
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from meiduo_mall.utils.my_loginview import LoginreqyiredView
from meiduo_mall.utils.response_code import RET
from orders.models import OrderInfo, OrderGoods
from users.models import Address


# 获取订单详情页
class OrderSettlement(LoginreqyiredView):
    def get(self, request):
        # 获取参数
        addresses = Address.objects.filter(user_id=request.user.id, is_deleted=False).all()

        # 获取用户选中购物车的数据
        redis_conn = get_redis_connection('carts')
        cart_dict = redis_conn.hgetall('carts_%s' % request.user.id)  # hgetall 返回键内所有成员
        sku_ids = redis_conn.smembers('selected_%s' % request.user.id)  # smembers范围键内的所有成员
        sku_list = []
        total_count = 0
        total_amount = 0.0
        for sku_id, count in cart_dict.items():
            sku = SKU.objects.get(id=sku_id)
            sku_dict = {
                "id": sku.id,
                "default_image_url": sku.default_image_url.url,
                "name": sku.name,
                "price": str(sku.price),
                "count": int(count),
                "amount": str(int(count) * sku.price),

            }
            sku_list.append(sku_dict)
            total_count += int(count)
            total_amount += float(count) * float(sku.price)
        context = {
            "addresses": addresses,
            "sku_list": sku_list,
            "total_count": total_count,
            "total_amount": "%.2f" % total_amount,  # 商品总价
            "freight ": 10,  # 运费
            "payment_amount": "%.2f" % (total_amount + 10)  # 商品总价 + 运费总价
        }
        return render(request, "place_order.html", context=context)

        # 订单提交


# 提交订单
class OrderCommit(LoginreqyiredView):
    @transaction.atomic
    def post(self, request):
        # 获取AJAX传过来的参数
        dict_data = json.loads(request.body.decode())
        pay_method = dict_data.get("pay_method")  # 用户选择的付款方式
        address_id = dict_data.get("address_id")  # 用户选择的收货地址)

        # 判断参数是否齐全
        if not all([pay_method, address_id]):
            return http.JsonResponse({"code": RET.DBERR, "errmsg": "参数有误"})

        # 判断地址是否存在
        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "地址不存在"})
        pay_method = int(pay_method)
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM["CASH"], OrderInfo.PAY_METHODS_ENUM["ALIPAY"]]:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "支付方式有误"})

        sid = transaction.savepoint()
        # 生成唯一的订单号   下单时间 + 9位随机数字 + 用户ID
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%09d%d" % (random.randint(0, 999999999), request.user.id)
        # 判断订单状态
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]

        order_info = OrderInfo.objects.create(
            order_id=order_id,
            user=request.user,
            address=address,
            total_count=0,
            total_amount=Decimal(0.0),
            freight=Decimal(10.0),
            pay_method=pay_method,
            status=status
        )

        # 获取用户选中购物车的数据
        redis_conn = get_redis_connection('carts')
        cart_dict = redis_conn.hgetall('carts_%s' % request.user.id)  # hgetall 返回键内所有成员
        sku_ids = redis_conn.smembers('selected_%s' % request.user.id)  # smembers范围键内的所有成员

        for sku_id in sku_ids:
            while True:
                #  获取下单商品数据或下单数量
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                if count > sku.stock:
                    transaction.savepoint_rollback(sid)
                    return http.JsonResponse({"code": RET.DATAERR, "errmsg": "库存不足"})
                # import time
                # time.sleep(5)
                # 减去库存
                old_stock = sku.stock  # 再次查询库存
                old_sales = sku.sales  # 查询销量
                new_stock = old_stock - count  # 老库存-用户买的商品数量
                new_sales = old_sales + count
                # 解决并发下单 库存的问题
                ret = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock,
                                                                            sales=new_sales)  # 改变返回0
                if ret == 0:
                    # transaction.savepoint_rollback(sid)
                    # return http.JsonResponse({"code": RET.DATAERR, "errmsg": "别人先得手啦，库存不足"})
                    continue

                # sku.stock -= count
                # sku.sales += count

                # 创建商品对象
                OrderGoods.objects.create(
                    order=order_info,
                    sku=sku,
                    count=count,
                    price=sku.price,
                )

                # 各个商品的数量 和商品总价价格累加
                order_info.total_count += count  # 订单总数量
                order_info.total_amount += (count * sku.price)  # 订单总金额
                # sku.save()

                break

        order_info.save()
        redis_conn.hdel('carts_%s' % request.user.id, *sku_ids)
        redis_conn.srem('selected_%s' % request.user.id, *sku_ids)
        transaction.savepoint_commit(sid)
        return http.JsonResponse({"code": RET.OK, "order_id": order_id})


# 支付成功
class OrderSuccessView(LoginreqyiredView):
    def get(self, request):
        order_id = request.GET.get("order_id")
        payment_amount = request.GET.get("payment_amount")
        pay_method = request.GET.get("pay_method")

        # 为空校验
        if not all([order_id, payment_amount, pay_method]):
            return http.HttpResponseForbidden("参数不全")

        try:
            order = OrderInfo.objects.get(order_id=order_id)
        except Exception as e:
            return http.HttpResponseForbidden("订单不存在")

        # 判断支付方式
        if pay_method not in ['1', '2']:
            return http.HttpResponseForbidden("支付方式有误")

        context = {
            "order_id": order_id,
            "payment_amount": payment_amount,
            "pay_method": pay_method
        }
        return render(request, "order_success.html", context=context)


        # 订单号校验是否存在


# 全部订单
class OrderInfoView(LoginreqyiredView):
    def get(self, request, page_num):
        # 获取用户订单数据
        orders = OrderInfo.objects.filter(user=request.user).order_by("-create_time").all()

        for order in orders:
            order.pay_method = OrderInfo.PAY_METHOD_CHOICES[order.pay_method - 1][1]
            order.status = OrderInfo.ORDER_STATUS_CHOICES[order.status - 1][1]

        paginate = Paginator(object_list=orders, per_page=3)
        page = paginate.page(page_num)
        order_list = page.object_list  # 当前页对象
        current_page = page.number  # 当前页面
        total_page = paginate.num_pages  # 总页数
        context = {
            "orders": order_list,
            "current_page": current_page,
            "total_page": total_page
        }
        return render(request, "user_center_order.html", context=context)


class OrderCommentView(LoginreqyiredView):
    def get(self, request):
        # 获取参数
        order_id = request.GET.get("order_id")
        try:
            order_info = OrderInfo.objects.get(order_id=order_id)
            order_goods = order_info.skus.all()
        except Exception as e:
            return render(request, "404.html")

        sku_list = []
        for order_good in order_goods:
            sku_dict = {
                "default_image_url": order_good.sku.default_image_url.url,
                "name": order_good.sku.name,
                "price": str(order_good.sku.price),
                "sku_id": order_good.sku_id,
                "order_id": order_id
            }
            sku_list.append(sku_dict)

        return render(request, "goods_judge.html", context={"skus": sku_list})

    @transaction.atomic
    def post(self, request):
        data_dict = json.loads(request.body.decode())
        order_id = data_dict.get("order_id")
        sku_id = data_dict.get("sku_id")
        comment = data_dict.get("comment")
        score = data_dict.get("score")
        is_anonymous = data_dict.get("is_anonymous")

        # 校验参数
        try:
            order_info = OrderInfo.objects.get(order_id=order_id)
        except Exception as e:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "订单不存在"})

        try:
            order_good = OrderGoods.objects.get(order_id=order_id, sku_id=sku_id)
        except:
            return http.JsonResponse({"code": RET.DBERR, "errmsg": "商品不存在"})

        if score > 5 or score < 1:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "分数不合理"})
        if not isinstance(is_anonymous, bool):
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "匿名评价数据有误"})

        # 开启事务
        sid = transaction.savepoint()
        try:
            # 数据入库
            order_good.comment = comment
            order_good.score = score
            order_good.is_anonymous = is_anonymous
            order_good.is_commented = True
            order_good.save()

            # 增加评论量
            order_good.sku.comments += 1
            order_good.sku.save()
            order_good.sku.spu.comments += 1
            order_good.sku.spu.save()
            # 修改订单状态
            order_info.status = OrderInfo.ORDER_STATUS_ENUM["FINISHED"]
            order_info.save()
        except Exception as e:
            transaction.savepoint_rollback(sid)  # 异常数据回滚
            http.JsonResponse({"code": RET.DBERR, "errmsg": "评价数量设置失败"})

        # 4,返回响应
        transaction.savepoint_commit(sid)
        return http.JsonResponse({"code": RET.OK, "errmsg": "评价成功"})


class SkuCommentView(View):
    def get(self, request, sku_id):
        try:
            order_goods = OrderGoods.objects.filter(sku_id=sku_id, is_commented=True).order_by("-create_time").all()
        except Exception as e:
            return http.JsonResponse({"code": RET.DBERR, "errmsg": "该商品无评价信息"})

            # 3,数据拼接
        comment_list = []
        for order_good in order_goods:
            comment_dict = {
                "username": order_good.order.user.username,
                "content": order_good.comment,
                "is_anonymous": order_good.is_anonymous
            }
            comment_list.append(comment_dict)

        # 4,返回响应
        return http.JsonResponse({"code": RET.OK, "goods_comment_list": comment_list})
